{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## template"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What is template? I don't know.\n",
    "\n",
    "Why we have to use it? I don't know."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "template <typename X, typename Y, typename Z>\n",
    "struct MyTemplateClass {\n",
    "    public:\n",
    "        X foo(Y&);\n",
    "    private:\n",
    "        Z* member;\n",
    "};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "template <typename X, typename Y, typename Z>\n",
    "X my_template_function(Y& arg1, const Z* arg2) {\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "template <typename X, typename Y>\n",
    "X sum(X arg1, Y arg2) { // we got two different type, it can be int and float\n",
    "    return arg1 + arg2;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3"
     ]
    }
   ],
   "source": [
    "#include <cstdio>\n",
    "printf(\"%d\", sum(1, 2.0));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Named Conversion Functions (Type conversion functions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similar to `int(3.34)` in Python.\n",
    "\n",
    "But it's more complex."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### const_cast"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Do not use it! It's a fucking stupid feature!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <cstdio>\n",
    "void no_const_function(const int& a_number) {\n",
    "    //a_number++; //compiler raise an error\n",
    "    auto& new_number = const_cast<int&>(a_number);\n",
    "    new_number++;\n",
    "    printf(\"%d\\n\", a_number);\n",
    "    printf(\"%d\\n\", new_number);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "23\n",
      "23\n"
     ]
    }
   ],
   "source": [
    "no_const_function(22)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What is 'cast'?\n",
    "\n",
    "The defination of this word is 'shape by pouring it into a mold while molten.'\n",
    "\n",
    "So it is similar to `convertion`, from one shape to another, from one type to another."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### static_cast"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is more like `int(3.34)` in Python."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "666 is the mark_of_the_beast."
     ]
    }
   ],
   "source": [
    "#include <cstdio>\n",
    "\n",
    "short increment_as_short(void* target) {\n",
    "    auto as_short = static_cast<short*>(target);\n",
    "    *as_short = *as_short + 1;\n",
    "    return *as_short;\n",
    "}\n",
    "\n",
    "short beast{ 665 };\n",
    "auto mark_of_the_beast = increment_as_short(&beast);\n",
    "printf(\"%d is the mark_of_the_beast.\", mark_of_the_beast);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### reinterpret_cast"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Useful only in embedded environments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "/*\n",
    "auto timer = reinterpret_cast<const unsigned long*>(0x1000);\n",
    "printf(\"Timer is %lu\", *timer);\n",
    "*/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## how to use template"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <cstddef>\n",
    "#include <cstdio>\n",
    "\n",
    "template<typename T>\n",
    "T mean(T* values, size_t length) {\n",
    "    T result{}; // you can also use 'T result;'\n",
    "    for(size_t i{}; i<length; i++) { // size_t = size_type = an interger that saves the size number\n",
    "        result += values[i];\n",
    "    }\n",
    "    return result / length;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "float: 2.000000\n"
     ]
    }
   ],
   "source": [
    "float nums_float[]  { 1.0f, 2.0f, 3.0f };\n",
    "const auto result1 = mean<float>(nums_float, 3); // inside the <> is the type of 'typename T'\n",
    "//const auto result1 = mean(nums_float, 3); // this also works\n",
    "printf(\"float: %f\\n\", result1);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "int: 2\n"
     ]
    }
   ],
   "source": [
    "const int nums_int[]  { 1, 2, 3 };\n",
    "const auto result2 = mean<int>(const_cast<int*>(nums_int), 3); // you should never use const_cast, remember?\n",
    "printf(\"int: %d\\n\", result2);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## how to use concepts and requires expression"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is used to make sure your type is able to do some oprations\n",
    "\n",
    "Old compiller may not support this feature."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "/*\n",
    "template<typename T>\n",
    "concept bool Averageable() {\n",
    "    return std::is_default_constructible<T>::value //'T result{}' is using a default constructor; '::value' will retuan a bool value\n",
    "        && requires(T a, T b) {\n",
    "        {a += b} -> T; // make sure 'T += T' still return a 'T'\n",
    "        {a / size_t{1} } -> T; // similar to the above comments; 'T' means type, by the way.\n",
    "    };\n",
    "}\n",
    "\n",
    "template<Averageable T>\n",
    "T mean(T* values, size_t length) {\n",
    "    T result{}; // you can also use 'T result;'\n",
    "    for(size_t i{}; i<length; i++) { // size_t = size_type = an interger that saves the size number\n",
    "        result += values[i];\n",
    "    }\n",
    "    return result / length;\n",
    "}\n",
    "*/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## a simpler way to use concepts and requires expression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "/*\n",
    "template<typename T>\n",
    "    requires std::is_default_constructible<T>::value\n",
    "\n",
    "T mean(T* values, size_t length) {\n",
    "    T result{}; // you can also use 'T result;'\n",
    "    for(size_t i{}; i<length; i++) { // size_t = size_type = an interger that saves the size number\n",
    "        result += values[i];\n",
    "    }\n",
    "    return result / length;\n",
    "}\n",
    "*/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## static_assert"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's the same as the python's `assert`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "static_assert(2==2, \"This must be right\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## non type tempalate parameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's like python's argument, which has no type."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "template<typename Any_type, size_t Index>\n",
    "void get(Any_type *arr) {\n",
    "    printf(\"%d\\n\", arr[Index]);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "int list[] = {1, 2, 3, 4};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "get<int, 0>(list);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "get<int, 3>(list);"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
